package com.ruijie.acl.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.AclPlanParameters;
import com.ruijie.acl.TimeRange;
import com.ruijie.acl.service.AccessGroupService;
import com.ruijie.acl.service.AceService;
import com.ruijie.acl.service.AclInterfaceService;
import com.ruijie.acl.service.AclPlanParametersService;
import com.ruijie.acl.service.DeviceAccessGroupService;
import com.ruijie.acl.service.DeviceTimeRangeService;
import com.ruijie.acl.service.TimeRangeService;
import com.ruijie.acl.task.config.TaskConfigAclDevice;
import com.ruijie.acl.task.model.AccessGroupInfo;
import com.ruijie.acl.task.model.AclInterfaceInfo;
import com.ruijie.acl.task.model.TimeRangeInfo;
import com.ruijie.acl.type.AclPlanTypeEnum;
import com.ruijie.acl.type.InterfaceAccessGroupTypeEnum;
import com.ruijie.acl.utils.AclConfigUtil;
import com.ruijie.acl.utils.AclUtil;
import com.ruijie.acl.web.config.Constants;
import com.ruijie.batch.core.factory.SpringConfigAware;
import com.ruijie.batch.plan.PlanParameters;
import com.ruijie.batch.plan.items.ItemParameters;
import com.ruijie.batch.task.ItemProcessResult;
import com.ruijie.emp.batch.task.AbstractDeviceExtendTasklet;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.device.DeviceInterface;
import com.ruijie.emp.system.service.TelnetTemplateService;
import com.ruijie.foundation.exception.BusinessException;

/**
 * 
 * <p>
 * Title: 下发ACL部署计划
 * </p>
 * <p>
 * Description: Function Description
 * </p>
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time: 2009-09-27
 * </p>
 * <p>
 * Update Time:
 * </p>
 * <p>
 * Updater:
 * </p>
 * <p>
 * Update Comments:
 * </p>
 * 
 * @author ASAI
 */
public class DeployAclDevice extends AbstractDeviceExtendTasklet implements SpringConfigAware {

	// private Log logger = LogFactory.getLog(DeployAclDevice.class);

	private TelnetTemplateService service;

	private AclPlanParametersService aclPlanParametersService;

	private AclInterfaceService aclInterfaceService;

	private AccessGroupService accessGroupService;

	private AceService aceService;

	private TimeRangeService timeRangeService;

	private DeviceAccessGroupService deviceAccessGroupService;

	private DeviceTimeRangeService deviceTimeRangeService;

	private TaskConfigAclDevice taskConfigAclDevice;

	private Map<String, String> paramMap = new HashMap<String, String>();
	
	//判断线程是否在使用这个类
	private boolean isThreedUsing=false;

	protected Map<String, String> parseParameters(ItemParameters itemParameters) {
		Map<String, String> paramMapNew=new HashMap<String,String>();
		for(String key:paramMap.keySet()){
			paramMapNew.put(key, paramMap.get(key));
		}
		//通知其他线程可以使用这个类
		this.isThreedUsing=false;
		synchronized(this){
			this.notifyAll();
		}
		return paramMapNew;
	}

	@SuppressWarnings("unchecked")
	public ItemProcessResult processItem(Object item, ItemParameters itemParameters) {
		//[start]保证只能有一个线程进入这个方法
		while(this.isThreedUsing){
			synchronized(this){
				try{
					//此类被其他线程占用中，等待其使用结束
					this.wait();
				}catch(InterruptedException e){
					throw new BusinessException(e);
				}
			}
		}
		//线程正在使用这个类
		this.isThreedUsing=true;
		//[end]
		ItemProcessResult result = new ItemProcessResult();
		paramMap.clear();
		Assert.notNull(item, "item is null");

		PlanParameters planParameters = new PlanParameters();

		AclPlanParameters aclPlanParamters = null;
		try {
			String aclPlanParamtersId = itemParameters
					.getParameterValue(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME);
			aclPlanParamters = aclPlanParametersService.get(Long.parseLong(aclPlanParamtersId));
		} catch (Exception ex) {
			throw new BusinessException("acl_deployment_initparam_error");
		}
		// 处理类型
		String dealType = aclPlanParamters.getDealType();

		List<TimeRange> timeRangeList = null;
		List<AccessGroup> accessGroupList = null;
		List<AclInterfaceInfo> aclInterfaceInfoList = null;
		List<AclInterfaceInfo> aclInterfaceInfoLogList = null;
		Map<String,AclInterfaceInfo> delInterfaceMap = null;
		String groupNames = "";
		String timeRangeNames = "";
		String interfaces = "";

		// 数据库处理

		// [start] 如果为添加部署
		if (dealType.equals(AclPlanTypeEnum.Add.toString())) {
			try {
				if (!AclUtil.empty(aclPlanParamters.getAccessGroups())) {
					accessGroupList = accessGroupService.findByIds(aclPlanParamters
							.getAccessGroups());
					// 转换组信息
					if (accessGroupList.size() > 0) {
						List<AccessGroupInfo> accessGroupInfoList = aceService
								.accessGroup2AccessGroupInfo(accessGroupList);
						planParameters.putParameter("accessGroupInfoList", accessGroupInfoList);
						groupNames = AclConfigUtil.convertAccessGroupNames(accessGroupInfoList);
						this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_GROUPNAMES, groupNames);
					}
				}

				// 转换时间段信息
				if (!AclUtil.empty(aclPlanParamters.getTimeRanges())) {
					timeRangeList = timeRangeService.findByIds(aclPlanParamters.getTimeRanges());
				} else {
					if (accessGroupList != null && accessGroupList.size() > 0) {
						timeRangeList = timeRangeService.findByAccessGroup(accessGroupList);
					}
				}
				if (timeRangeList != null && timeRangeList.size() > 0) {
					List<TimeRangeInfo> timeRangeInfoList = AclConfigUtil
							.timeRangeList2TimeRangeInfoList(timeRangeList);
					planParameters.putParameter("timerangeInfoList", timeRangeInfoList);
					timeRangeNames = AclConfigUtil.convertTimeRangeNames(timeRangeInfoList);
					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_TIMENAMES, timeRangeNames);
				}
				if (!AclUtil.empty(aclPlanParamters.getInterfaces())) {
					aclInterfaceInfoList = this.convertString2AclInterfaceInfo(aclPlanParamters
							.getInterfaces());
					aclInterfaceInfoLogList = this.convertString2AclInterfaceInfo(aclPlanParamters
							.getInterfacesLog());
					planParameters.putParameter("aclInterfaceInfoList", aclInterfaceInfoList);
					delInterfaceMap = aclInterfaceService.
						getAclInterfaceInfoMapByDevice((Device) item, aclInterfaceInfoList);//获得旧的接口
					planParameters.putParameter("delInterfaceMap", delInterfaceMap);
					interfaces = AclConfigUtil.convertInterfaceStrings(aclInterfaceInfoLogList);
					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_INTERFACES, interfaces);
				}
			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_initparam_error");
			}

			result = taskConfigAclDevice.processItem(item, planParameters);

			try {
				// 不用处理时间段与组之间的关系。
				// 插入组和设备之间的关系。
				deviceAccessGroupService.addAccessGroupDevices(accessGroupList, (Device) item);
				// 备份设备中的组
				this.accessGroupService.saveSameWithDevice(accessGroupList, (Device) item);
				// 变更组的变更警示
				if (accessGroupList != null && accessGroupList.size() > 0) {
					for (AccessGroup accessGroup : accessGroupList) {
						try {
							accessGroupService.refresh(accessGroup);
							accessGroup.setIsChanged(false);
							accessGroupService.update(accessGroup);
						} catch (Exception ex) {
							groupNames = "," + groupNames + ",";
							groupNames = groupNames.replaceAll("," + accessGroup.getName() + ",", ",");
							if (groupNames.length() > 1){
								groupNames = groupNames.substring(1, groupNames.length() - 1);
							}else{
								groupNames = "";
							}
						}
					}
				}

				// 备份设备中的时间段
				this.timeRangeService.saveSameWithDevice(timeRangeList, (Device) item);

				// 变更时间段的变更警示
				if (timeRangeList != null && timeRangeList.size() > 0) {
					for (TimeRange timeRange : timeRangeList) {
						try {
							timeRangeService.refresh(timeRange);
							timeRange.setIsChanged(false);
							timeRangeService.update(timeRange);
						} catch (Exception ex) {
							timeRangeNames = "," + timeRangeNames + ",";
							timeRangeNames = timeRangeNames.replaceAll("," + timeRange.getName() + ",", ",");
							if (timeRangeNames.length() > 1){
								timeRangeNames = timeRangeNames.substring(1, timeRangeNames.length() - 1);
							}else{
								timeRangeNames = "";
							}
						}
					}
				}

				// 插入组和接口的关系。
				aclInterfaceService.addAclInterfaces(aclInterfaceInfoList, (Device) item);

				// 插入时间段和设备的关系。
				deviceTimeRangeService.addTimeRangeDevices(timeRangeList, (Device) item);
				this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_GROUPNAMES, groupNames);
				this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_TIMENAMES, timeRangeNames);
				this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_INTERFACES, interfaces);

			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_updatedatabase_error");
			}

		}
		// [end] 添加部署

		// [start] 如果为接口应用部署

		else if (dealType.equals(AclPlanTypeEnum.AddInterface.toString())) {
			try {
				if (!AclUtil.empty(aclPlanParamters.getInterfaces())) {
					aclInterfaceInfoList = this.convertString2AclInterfaceInfo(aclPlanParamters
							.getInterfaces());
					planParameters.putParameter("aclInterfaceInfoList", aclInterfaceInfoList);
					delInterfaceMap = aclInterfaceService.
						getAclInterfaceInfoMapByDevice((Device) item, aclInterfaceInfoList);//获得旧的接口
					planParameters.putParameter("delInterfaceMap", delInterfaceMap);
					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_INTERFACES,
							AclConfigUtil.convertInterfaceStrings(aclInterfaceInfoList));
				}

			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_initparam_error");
			}
			result = taskConfigAclDevice.processItem(item, planParameters);
			// 不用插入时间段与组之间的关系。
			// 不用插入组和设备之间的关系。
			// 插入组和接口的关系。
			try {
				aclInterfaceService.addAclInterfaces(aclInterfaceInfoList, (Device) item);
			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_updatedatabase_error");
			}
		}
		// [end] 接口应用部署

		return result;
	}

	/**
	 * 把字符串转换成计划接口类型
	 * 
	 * 
	 * @param planInterfaceString
	 * @return
	 */
	private List<AclInterfaceInfo> convertString2AclInterfaceInfo(String planInterfaceString) {
		List<AclInterfaceInfo> aclInterfaceInfoList = null;
		if (!AclUtil.empty(planInterfaceString)) {
			aclInterfaceInfoList = new ArrayList<AclInterfaceInfo>();
			String[] arrAclPlanInterfaceList = planInterfaceString.split(";");
			for (String planInterfaceStr : arrAclPlanInterfaceList) {
				AclInterfaceInfo aclPlanInterface = new AclInterfaceInfo();
				String[] arrAclPlanInterface = planInterfaceStr.split(",");
				if (arrAclPlanInterface.length == 3) {
					DeviceInterface deviceInterface = aclInterfaceService.getDeviceInterface(Long
							.parseLong(arrAclPlanInterface[0]));
					aclPlanInterface.setIfName(deviceInterface.getName());
					AccessGroup accessGroup = aclInterfaceService.getAccessGroup(Long
							.parseLong(arrAclPlanInterface[2]));
					// 如果ACL组存在
					if (accessGroup != null){
						String accessGroupType = arrAclPlanInterface[1];
						if (accessGroupType.equals(InterfaceAccessGroupTypeEnum.In.toString())) {
							aclPlanInterface.setInAccessGroupName(accessGroup.getName());
	
						} else if (accessGroupType.equals(InterfaceAccessGroupTypeEnum.Out.toString())) {
							aclPlanInterface.setOutAccessGroupName(accessGroup.getName());
	
						} else if (accessGroupType
								.equals(InterfaceAccessGroupTypeEnum.InOut.toString())) {
							aclPlanInterface.setInAccessGroupName(accessGroup.getName());
							aclPlanInterface.setOutAccessGroupName(accessGroup.getName());
						}
						aclInterfaceInfoList.add(aclPlanInterface);
					}
				}
			}
		}
		return aclInterfaceInfoList;
	}

	public void setService(TelnetTemplateService service) {
		this.service = service;
	}

	public void setAclInterfaceService(AclInterfaceService aclInterfaceService) {
		this.aclInterfaceService = aclInterfaceService;
	}

	public AclPlanParametersService getAclPlanParametersService() {
		return aclPlanParametersService;
	}

	public void setAclPlanParametersService(AclPlanParametersService aclPlanParametersService) {
		this.aclPlanParametersService = aclPlanParametersService;
	}

	public AccessGroupService getAccessGroupService() {
		return accessGroupService;
	}

	public void setAccessGroupService(AccessGroupService accessGroupService) {
		this.accessGroupService = accessGroupService;
	}

	public AceService getAceService() {
		return aceService;
	}

	public void setAceService(AceService aceService) {
		this.aceService = aceService;
	}

	public TimeRangeService getTimeRangeService() {
		return timeRangeService;
	}

	public void setTimeRangeService(TimeRangeService timeRangeService) {
		this.timeRangeService = timeRangeService;
	}

	public TaskConfigAclDevice getTaskConfigAclDevice() {
		return taskConfigAclDevice;
	}

	public void setTaskConfigAclDevice(TaskConfigAclDevice taskConfigAclDevice) {
		this.taskConfigAclDevice = taskConfigAclDevice;
	}

	public TelnetTemplateService getService() {
		return service;
	}

	public AclInterfaceService getAclInterfaceService() {
		return aclInterfaceService;
	}

	public DeviceAccessGroupService getDeviceAccessGroupService() {
		return deviceAccessGroupService;
	}

	public void setDeviceAccessGroupService(DeviceAccessGroupService deviceAccessGroupService) {
		this.deviceAccessGroupService = deviceAccessGroupService;
	}

	public DeviceTimeRangeService getDeviceTimeRangeService() {
		return deviceTimeRangeService;
	}

	public void setDeviceTimeRangeService(DeviceTimeRangeService deviceTimeRangeService) {
		this.deviceTimeRangeService = deviceTimeRangeService;
	}

}
